

package top.continew.admin.question.manger.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.question.manger.base.PageFactory;
import top.continew.admin.question.manger.base.PingYinUtil;
import top.continew.admin.question.manger.service.model.*;
import top.continew.admin.question.mapper.test.TestMapper;
import top.continew.admin.question.model.ClassCourseTest;
import top.continew.admin.question.model.question.QuestionSet;
import top.continew.admin.question.model.question.QuestionSetQuestion;
import top.continew.admin.question.model.test.*;
import top.continew.admin.question.manger.service.MangerQuestionService;
import top.continew.admin.question.manger.service.TestService;

import top.continew.admin.question.manger.service.msg.MessageBean;
import top.continew.admin.question.manger.service.msg.MessageTopic;
import top.continew.admin.question.manger.service.msg.MessageType;
import top.continew.starter.core.validation.ValidationUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service

public class TestServiceImpl implements TestService {
    private TestMapper testMapper;

    private MangerQuestionService mangerQuestionService;

    public TestServiceImpl(TestMapper testMapper, MangerQuestionService mangerQuestionService) {
        this.testMapper = testMapper;
        this.mangerQuestionService = mangerQuestionService;
    }

    @Override
    public List<TestListVO> getList(TestParam testParam) {
        return PageFactory.page(() -> testMapper.getList(testParam, UserContextHolder.getUserId()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AddUpTest addUpTest(AddUpTest addUpTest) {
        // 添加修改试卷
        Test test = new Test();
        BeanUtils.copyProperties(addUpTest, test);
        if (addUpTest.getId() == null) {
            test.setEditPeople(UserContextHolder.getUserId());
            test.setEditStatus(0L);
            test.setStatus(0L);
        } else {
            ValidationUtils.throwIf(!testIsReadOnly(new Test().selectById(addUpTest.getId())), "您无权限编辑该试卷!");
        }
        if (StrUtil.isEmpty(addUpTest.getIsNew())) {
            test.setIsNew(1);
        }
        if (StrUtil.isEmpty(test.getCode())) {
            test.setCode(PingYinUtil.getPYIndexStr(test.getTitle(), true));
        }

        test.setYear(Long.parseLong(addUpTest.getYear() == null ? "0" : addUpTest.getYear()));
        test.insertOrUpdate();
        // 科目
        if (!addUpTest.getCategory().isEmpty()) {
            new TestSubjects().delete(new QueryWrapper<TestSubjects>().eq("test_id", addUpTest.getId()));
            addUpTest.getCategory().forEach(s -> {
                TestSubjects testSubject = new TestSubjects();
                testSubject.setSubjectsId(s);
                testSubject.setTestId(test.getId());
                testSubject.insert();
            });
        }
        // 学科
        if (!addUpTest.getTestSubject().isEmpty()) {
            new TestSubjectType().delete(new QueryWrapper<TestSubjectType>().eq("testId", addUpTest.getId()));
            addUpTest.getTestSubject().forEach(s -> {
                TestSubjectType testSubject = new TestSubjectType();
                testSubject.setSubjectTypeId(s);
                testSubject.setTestId(test.getId());
                testSubject.insert();
            });
        }
        // 学段
        if (!addUpTest.getTestSchoolSection().isEmpty()) {
            new TestSchoolSection().delete(new QueryWrapper<TestSchoolSection>().eq("testId", addUpTest.getId()));
            addUpTest.getTestSchoolSection().forEach(s -> {
                TestSchoolSection testSchoolSection = new TestSchoolSection();
                testSchoolSection.setSchoolSectionId(s);
                testSchoolSection.setTestId(test.getId());
                testSchoolSection.insert();
            });
        }
        // 考试区域
        if (!addUpTest.getTestArea().isEmpty()) {
            new TestArea().delete(new QueryWrapper<TestArea>().eq("testId", addUpTest.getId()));
            addUpTest.getTestArea().forEach(s -> {
                TestArea testArea = new TestArea();
                testArea.setAreaId(s.get(s.size() - 1));
                testArea.setTestId(test.getId());
                testArea.setAreaLinkedList(JSON.toJSONString(s));
                testArea.insert();
            });
        }
        addUpTest.setId(test.getId());
        addUpTest.setCode(test.getCode());
        return addUpTest;
    }

    /**
     * 试卷当前用户是否可编辑
     */
    private boolean testIsReadOnly(Test test) {
        return switch (test.getStatus().intValue()) {
            case 0 -> !Objects.equals(UserContextHolder.getUserId(), test.getEditPeople());
            case 3 -> !Objects.equals(UserContextHolder.getUserId(), test.getCheckPeople());
            case 4 -> !Objects.equals(UserContextHolder.getUserId(), test.getReviewPeople());
            default -> true;
        };
    }

    @Override
    public TestInfoVO getInfo(long id) {
        TestInfoVO testInfoVO = new TestInfoVO();
        Test test = new Test().selectById(id);
        ValidationUtils.throwIfEmpty(test, "试卷没有找到~");
        BeanUtils.copyProperties(test, testInfoVO);
        // 获取区域
        List<TestArea> testAreas = new TestArea().selectList(new QueryWrapper<TestArea>().eq("testId", id));
        testInfoVO.setTestArea(testAreas.stream().map(s -> {
            return JSON.parseArray(s.getAreaLinkedList(), Long.class);
        }).collect(Collectors.toList()));
        // 获取学科
        List<TestSubjectType> testSubjectTypes = new TestSubjectType().selectList(new QueryWrapper<TestSubjectType>()
            .eq("testId", id));
        long[] testSubjectTypesIds = testSubjectTypes.stream().mapToLong(TestSubjectType::getSubjectTypeId).toArray();
        testInfoVO.setTestSubject(testSubjectTypesIds);
        // 获取学段
        List<TestSchoolSection> testSchoolSections = new TestSchoolSection()
            .selectList(new QueryWrapper<TestSchoolSection>().eq("testId", id));
        long[] testSchoolSectionIds = testSchoolSections.stream()
            .mapToLong(TestSchoolSection::getSchoolSectionId)
            .toArray();
        // 获取科目
        List<TestSubjects> testSchools = new TestSubjects().selectList(new QueryWrapper<TestSubjects>()
            .eq("test_id", id));
        long[] testSchoolsIds = testSchools.stream().mapToLong(TestSubjects::getSubjectsId).toArray();
        testInfoVO.setCategory(testSchoolsIds);
        testInfoVO.setTestSchoolSection(testSchoolSectionIds);
        testInfoVO.setYear(String.valueOf(test.getYear()));
        testInfoVO.setReadonly(testIsReadOnly(test));
        return testInfoVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public TestStructureVO saveTestStructure(long id, Long testStructureId, String name, double score) {
        Test test = new Test().selectById(id);
        ValidationUtils.throwIfEmpty(test, "试卷信息错误!");
        ValidationUtils.throwIf(!testIsReadOnly(test), "您暂无权限编辑该试卷!");
        TestStructure testStructure = new TestStructure().selectById(testStructureId);
        if (testStructure == null) {
            // 试卷题集
            QuestionSet questionSet = new QuestionSet();
            questionSet.setTitle(test.getTitle() + '-' + name);
            questionSet.setType(test.getDataType());
            questionSet.setUserId(0);
            questionSet.insert();
            // 试卷结构
            testStructure = new TestStructure();
            testStructure.setTestId(id);
            testStructure.setTitle(name);
            testStructure.setScore(score);
            testStructure.setSort(System.currentTimeMillis() * 1000);
            testStructure.setQuestionSetId(questionSet.getId());
            testStructure.insert();
        } else {
            testStructure.setTitle(name);
            testStructure.setScore(score);
            testStructure.updateById();
        }
        TestStructureVO testStructureVO = new TestStructureVO();
        BeanUtils.copyProperties(testStructure, testStructureVO);
        return testStructureVO;
    }

    @Override
    public List<TestStructureVO> getTestStructure(long id) {
        return new TestStructure().selectList(new QueryWrapper<TestStructure>().eq("testId", id)
            .orderByAsc("sort")
            .orderByDesc("utime")).stream().map(s -> {
                TestStructureVO testStructureVO = new TestStructureVO();
                BeanUtils.copyProperties(s, testStructureVO);
                selectQuestion(testStructureVO);
                return testStructureVO;
            }).collect(Collectors.toList());
    }

    private void selectQuestion(TestStructureVO testStructureVO) {
        testStructureVO.setQuestion(mangerQuestionService.getQuestionByQuestionSet(testStructureVO.getQuestionSetId()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteTestStructure(String testId, String id) {
        Test test = new Test().selectById(testId);
        ValidationUtils.throwIfEmpty(test, "试卷不存在!");
        ValidationUtils.throwIf(!testIsReadOnly(test), "您没有权限删除该试卷结构!");
        TestStructure testStructure = new TestStructure().selectById(id);
        ValidationUtils.throwIfEmpty(testStructure, "试卷结构不存在!");
        testStructure.deleteById();
        // 删除题集
        new QuestionSet().deleteById(testStructure.getQuestionSetId());
        // 删除相关的题集题目关联
        new QuestionSetQuestion().delete(new QueryWrapper<QuestionSetQuestion>().eq("question_set_id", testStructure
            .getQuestionSetId()));
    }

    @Override
    public void testStructureSort(String testId, String id, long sort) {
        Test test = new Test().selectById(testId);
        ValidationUtils.throwIfEmpty(test, "试卷不存在!");
        ValidationUtils.throwIf(!testIsReadOnly(test), "您没有权限修改该试卷结构!");
        TestStructure testStructure = new TestStructure().selectById(id);
        ValidationUtils.throwIfEmpty(testStructure, "试卷结构不存在!");
        testStructure.setSort(sort);
        testStructure.updateById();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void commitCheck(String testId, Long checkPeople) {
        Test test = new Test().selectById(testId);
        ValidationUtils.throwIfEmpty(test, "试卷不存在!");
        hasCommitPermission(test);
        test.setEditStatus(1L);
        test.setCheckPeople(checkPeople);
        test.setCheckStatus(0L);
        test.setStatus(3L);
        test.updateById();
        // 提交试卷题目
        this.testMapper.checkTestQuestion(test.getId(), checkPeople, System.currentTimeMillis());
    }

    @Override
    public void commitReview(String testId, Long reviewPeople) {
        Test test = new Test().selectById(testId);
        ValidationUtils.throwIfEmpty(test, "试卷不存在!");
        hasCommitPermission(test);
        test.setReviewPeople(reviewPeople);
        test.setCheckStatus(1L);
        test.setReviewStatus(0L);
        test.setStatus(4L);
        test.updateById();
    }

    @Override
    public void review(String testId) {
        Test test = new Test().selectById(testId);
        ValidationUtils.throwIfEmpty(test, "试卷不存在!");
        hasCommitPermission(test);
        test.setReviewStatus(1L);
        test.setStatus(5L);
        test.updateById();
    }

    @Override
    public void rejectReview(String testId, String msg) {
        Test test = new Test().selectById(testId);
        ValidationUtils.throwIfEmpty(test, "试卷不存在!");
        hasCommitPermission(test);
        test.setCheckStatus(2L);
        test.setStatus(3L);
        test.updateById();
        MessageBean.builder()
            .topic(MessageTopic.PAPER_REVIEW_REJECTION)
            .message("您好,您提交的试卷编号为:" + test.getCode() + "的试卷审核被驳回,驳回理由:" + msg)
            .type(MessageType.ERROR)
            .url("{\"path\":\"/testInfo\",\"query\":{\"id\":" + testId + "}}")
            .build()
            .addCustomer(test.getCheckPeople(), 2)
            .send();
    }

    @Override
    public void rejectReviewMultiple(String testIds, String msg) {
        String[] ids = testIds.split(",");
        ValidationUtils.throwIf(ids.length > 0, "驳回数量必须大于0!");
        // 获取可以驳回的试卷
        LambdaQueryWrapper<Test> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Test::getReviewStatus, 1L);
        queryWrapper.eq(Test::getStatus, 5L);
        queryWrapper.isNotNull(Test::getReviewPeople);
        queryWrapper.in(Test::getId, ids);
        List<Test> tests = this.testMapper.selectList(queryWrapper);
        List<Long> updateIds = tests.stream().map(Test::getId).collect(Collectors.toList());

        // 可以驳回的id为空时，直接跳过
        ValidationUtils.throwIf(updateIds.size() > 0, "通过状态筛选后无可驳回试卷!");
        // 设置驳回
        this.testMapper.rejectReviewMultiple(updateIds, System.currentTimeMillis());
        // 发送消息
        for (Test t : tests) {
            MessageBean.builder()
                .topic(MessageTopic.PAPER_REVIEW_REJECTION)
                .message("您好,您提交的试卷编号为:" + t.getCode() + "的试卷审核被驳回,驳回理由:" + (msg != null && !msg.equals("")
                    ? msg
                    : "无"))
                .type(MessageType.ERROR)
                .url("{\"path\":\"/testInfo\",\"query\":{\"id\":" + t.getId() + "}}")
                .build()
                .addCustomer(t.getCheckPeople(), 2)
                .send();
        }
    }

    @Override
    public void rejectCheck(String testId, String msg) {
        Test test = new Test().selectById(testId);
        ValidationUtils.throwIfEmpty(test, "试卷不存在!");
        hasCommitPermission(test);
        test.setStatus(0L);
        test.setEditStatus(2L);
        test.updateById();
        MessageBean.builder()
            .topic(MessageTopic.TEST_PAPER_REJECTION)
            .message("您好,您提交的试卷编号为:" + test.getCode() + "的试卷校验被驳回,驳回理由:" + msg)
            .type(MessageType.ERROR)
            .url("{\"path\":\"/testInfo\",\"query\":{\"id\":" + testId + "}}")
            .build()
            .addCustomer(test.getEditPeople(), 2)
            .send();
    }

    @Override
    public void rejectCheckMultiple(List<Long> testIds, String msg) {
        ValidationUtils.throwIf(testIds.size() > 0, "驳回数量必须大于0!");
        // 获取可以驳回的试卷
        LambdaQueryWrapper<Test> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Test::getEditStatus, 1L);
        queryWrapper.eq(Test::getStatus, 3L);
        queryWrapper.eq(Test::getCheckStatus, 0L);
        queryWrapper.isNotNull(Test::getCheckPeople);
        queryWrapper.in(Test::getId, testIds);
        List<Test> tests = this.testMapper.selectList(queryWrapper);
        List<Long> updateIds = tests.stream().map(Test::getId).collect(Collectors.toList());

        // 可以驳回的id为空时，直接跳过
        ValidationUtils.throwIf(updateIds.size() > 0, "通过状态筛选后无可驳回试卷!");

        // 设置驳回
        this.testMapper.rejectCheckMultiple(updateIds, System.currentTimeMillis());
        // 发送消息
        for (Test t : tests) {
            MessageBean.builder()
                .topic(MessageTopic.TEST_PAPER_REJECTION)
                .message("您好,您提交的试卷编号为:" + t.getCode() + "的试卷校验被驳回,驳回理由:" + (msg != null && !msg.equals("")
                    ? msg
                    : "无"))
                .type(MessageType.ERROR)
                .url("{\"path\":\"/testInfo\",\"query\":{\"id\":" + t.getId() + "}}")
                .build()
                .addCustomer(t.getEditPeople(), 2)
                .send();
        }
    }

    @Override
    public double saveQuestion(Long testStructureId,
                               Long testId,
                               long questionId,
                               double score,
                               boolean isUpdateProvenance) {
        TestStructure testStructure = new TestStructure().selectOne(new QueryWrapper<TestStructure>()
            .eq("testId", testId)
            .eq("id", testStructureId));
        ValidationUtils.throwIfEmpty(testStructure, "试卷结构异常,请重新添加!");
        QueryWrapper<QuestionSetQuestion> queryWrapper = new QueryWrapper<QuestionSetQuestion>()
            .eq("question_id", questionId)
            .eq("question_set_id", testStructure.getQuestionSetId());
        QuestionSetQuestion questionSetQuestion = new QuestionSetQuestion().selectOne(queryWrapper);
        if (questionSetQuestion != null) {
            questionSetQuestion.setScore(score);
            questionSetQuestion.update(queryWrapper);
            return questionSetQuestion.getScore();
        }
        questionSetQuestion = new QuestionSetQuestion();
        questionSetQuestion.setQuestionId(questionId);
        questionSetQuestion.setQuestionSetId(testStructure.getQuestionSetId());
        questionSetQuestion.setScore(score);
        questionSetQuestion.setSort(System.currentTimeMillis() * 1000);
        questionSetQuestion.setStatus(1L);
        questionSetQuestion.insert();
        if (isUpdateProvenance) {
            Test test = new Test().selectById(testId);
            this.mangerQuestionService.updateOfficialQuestion(questionId, "1", test.getTitle(), String.valueOf(test
                .getYear()));
        }
        return score;
    }

    @Override
    public void upQuestion(Long testStructureId, Long testId, String questionId, long sort) {
        TestStructure testStructure = new TestStructure().selectOne(new QueryWrapper<TestStructure>()
            .eq("testId", testId)
            .eq("id", testStructureId));
        ValidationUtils.throwIfEmpty(testStructure, "试卷结构异常,请重新添加!");
        QueryWrapper<QuestionSetQuestion> queryWrapper = new QueryWrapper<QuestionSetQuestion>()
            .eq("question_id", questionId)
            .eq("question_set_id", testStructure.getQuestionSetId());
        QuestionSetQuestion questionSetQuestion = new QuestionSetQuestion().selectOne(queryWrapper);
        ValidationUtils.throwIfEmpty(questionSetQuestion, "题目异常!");
        questionSetQuestion.setSort(sort);
        questionSetQuestion.update(queryWrapper);
    }

    @Override
    public void deleteTestQuestion(Long testStructureId, Long testId, String questionId) {
        TestStructure testStructure = new TestStructure().selectOne(new QueryWrapper<TestStructure>()
            .eq("testId", testId)
            .eq("id", testStructureId));
        ValidationUtils.throwIfEmpty(testStructure, "试卷结构异常,请重新添加!");
        QueryWrapper<QuestionSetQuestion> queryWrapper = new QueryWrapper<QuestionSetQuestion>()
            .eq("question_id", questionId)
            .eq("question_set_id", testStructure.getQuestionSetId());
        QuestionSetQuestion questionSetQuestion = new QuestionSetQuestion().selectOne(queryWrapper);
        ValidationUtils.throwIfEmpty(questionSetQuestion, "题目异常!");
        questionSetQuestion.delete(queryWrapper);
    }

    private void hasCommitPermission(Test test) {
        switch (test.getStatus().intValue()) {
            case 0:
                ValidationUtils.throwIf(test.getEditPeople().equals(UserContextHolder.getUserId()), "您没有权限提交该试卷的校验!");
                return;
            case 3:
                ValidationUtils.throwIf(test.getCheckPeople().equals(UserContextHolder.getUserId()), "您没有权限提交该试卷的审核!");
                return;
            case 4:
                ValidationUtils.throwIf(test.getReviewPeople().equals(UserContextHolder.getUserId()), "您没有权限审核该试卷!");
                return;

        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delTest(Long id, Long userId) {
        LambdaQueryWrapper<Test> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Test::getId, id);
        queryWrapper.eq(Test::getStatus, Test.STATUS_CREATE);
        queryWrapper.in(Test::getEditStatus, Arrays.asList(Test.STATUS_TS, Test.STATUS_REJECTED));
        queryWrapper.eq(Test::getEditPeople, userId);
        boolean flag = new Test().selectCount(queryWrapper) > 0;
        ValidationUtils.throwIf(flag, "不可删除，请检查试卷状态及录入人");

        boolean isExist = testMapper.verTestExistQuestion(id) > 0;
        ValidationUtils.throwIf(!isExist, "该试卷存在未删除的题目，请先删除对应题目");

        this.delTestStructure(id);

        return new Test().delete(queryWrapper);
    }

    /**
     * 删除试卷结构
     *
     * @param testId
     */
    private void delTestStructure(Long testId) {
        LambdaQueryWrapper<TestStructure> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TestStructure::getTestId, testId);
        List<TestStructure> testStructureList = new TestStructure().selectList(queryWrapper);
        if (testStructureList.size() > 0) {
            List<Long> setIds = testStructureList.stream()
                .map(TestStructure::getQuestionSetId)
                .collect(Collectors.toList());
            this.delQuestionSet(setIds);
            new TestStructure().delete(queryWrapper);
        }
    }

    /**
     * 删除题集及关联关系
     *
     * @param setIds
     */
    private void delQuestionSet(List<Long> setIds) {
        LambdaQueryWrapper<QuestionSet> questionSetQuery = new LambdaQueryWrapper<>();
        questionSetQuery.in(QuestionSet::getId, setIds);
        LambdaQueryWrapper<QuestionSetQuestion> questionSetQuestionQuery = new LambdaQueryWrapper<>();
        questionSetQuestionQuery.in(QuestionSetQuestion::getQuestionSetId, setIds);

        // 删除题集
        new QuestionSet().delete(questionSetQuery);
        // 删除相关的题集题目关联
        new QuestionSetQuestion().delete(questionSetQuestionQuery);
    }

    @Override
    public boolean verExistNoReviewQuestion(Long testId) {
        return this.testMapper.verExistNoReviewQuestion(testId) > 0;
    }

    @Override
    public boolean verExistStructureQuestion(Long id) {
        return this.testMapper.verExistStructureQuestion(id) > 0;
    }

    @Override
    public void bindClassOrCurriculum(long testId, long type, long typeId) {
        ClassCourseTest classCourseTest = new ClassCourseTest().selectOne(new QueryWrapper<ClassCourseTest>()
            .eq("type", type)
            .eq("type_id", typeId)
            .eq("test_id", testId));
        if (classCourseTest == null) {
            classCourseTest = new ClassCourseTest();
            classCourseTest.setTestId(testId);
            classCourseTest.setType(String.valueOf(type));
            classCourseTest.setTypeId(typeId);
            classCourseTest.setStatus("0");
            classCourseTest.setTimeLimit("1");
            classCourseTest.setCtime(System.currentTimeMillis());
            classCourseTest.setUtime(System.currentTimeMillis());
            classCourseTest.insert();
        }
    }

    @Override
    public List<Value> getClassOrCurriculum(long testId) {
        List<ClassCourseTest> classCourseTest = new ClassCourseTest().selectList(new QueryWrapper<ClassCourseTest>()
            .eq("test_id", testId));
        if (classCourseTest == null) {
            return new ArrayList<>();
        }
        return classCourseTest.stream().map(res -> {
            Value value = new Value();
            value.setLabel(String.valueOf(res.getTypeId()));
            value.setValue(res.getType());
            return value;
        }).collect(Collectors.toList());
    }

    @Override
    public List<SpotCheckTestVO> getSpotCheckTestList(QuerySpotCheckTest querySpotCheckTest) {
        return PageFactory.page(() -> testMapper.getSpotCheckTestList(querySpotCheckTest));
    }

    @Override
    public SpotCheckQuestionSum getSpotCheckQuestionSum(QuerySpotCheckTest querySpotCheckTest) {
        return testMapper.getSpotCheckQuestionSum(querySpotCheckTest);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchBindClassOrCurriculum(long id, List<Value> values) {
        //1.获取所有的关联
        List<ClassCourseTest> classCourseTest = new ClassCourseTest().selectList(new QueryWrapper<ClassCourseTest>()
            .eq("test_id", id));
        //2.删除多余的关联
        classCourseTest.stream()
            .filter(res -> values.stream().noneMatch(item -> item.getValue().equals(res.getTypeId() + "")))
            .forEach(Model::deleteById);
        //3.新增没有的关联
        values.stream()
            .filter(res -> classCourseTest.stream().noneMatch(item -> res.getLabel().equals(item.getTypeId() + "")))
            .forEach(res -> {
                bindClassOrCurriculum(id, Long.parseLong(res.getLabel()), Long.parseLong(res.getValue()));
            });
    }
}
